package com.hup.winHolderService.service;

import com.hup.utils.commons.DateBuilder;
import com.hup.utils.commons.TextUtil;
import com.hup.utils.commons.hardware.HRobotJni;
import com.hup.utils.io.batch.BatchUtil;
import com.hup.utils.io.batch.function.ScQc;
import com.hup.winHolderService.framework.exception.AppLogger;
import com.hup.winHolderService.model.po.AppConfig;
import com.hup.winHolderService.view.NotMutedFrame;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 定时任务
 *
 * @author hugan
 * @date 2023/10/11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ScheduleService {

    @Getter
    private final Timer timer = new Timer("MySchedule");
    private final AppConfig appConfig;
    private LockTask lockTask;
    private KillWinUpdateTask killWinUpdateTask;

    @PostConstruct
    public void init() {
        log.info("appConfig={}", appConfig);
        if (appConfig.isEnableKillWinUpdateTask()) {
            killWinUpdateTask = KillWinUpdateTask.doSchedule(timer);
        }
    }

    //lockPlan =====
    public void lockPlan(int minute) {
        if (lockTask != null) lockTask.cancel();
        lockTask = new LockTask(minute);
        //timer.schedule(lockTask, 2000L);//test
        timer.schedule(lockTask, minute * 60 * 1000L);
        log.info("lockPlan={}", lockTask.actionTime);
    }

    public void lockPlanCancel() {
        if (lockTask == null) return;
        log.info("lockPlanCancel");
        lockTask.cancel();
        lockTask = null;
    }

    public String lockPlanTime() {
        if (lockTask == null) return null;
        return lockTask.actionTime;
    }

    //killWinUpdateTask =====
    public boolean isEnableKillWinUpdateTask() {
        return appConfig.isEnableKillWinUpdateTask();
    }

    public void setEnableKillWinUpdateTask(boolean enable) {
        log.info("enable={}", enable);
        appConfig.setEnableKillWinUpdateTask(enable);
        appConfig.save();
        if (enable) {
            if (killWinUpdateTask != null) return;
            killWinUpdateTask = KillWinUpdateTask.doSchedule(timer);
        } else {
            if (killWinUpdateTask == null) return;
            killWinUpdateTask.cancel();
            killWinUpdateTask = null;
        }
    }

    /**
     * 停播&静音&锁屏
     * 一次性任务
     */
    private class LockTask extends TimerTask {
        private static final int VK_MEDIA_STOP = 0xB2;

        /**
         * 执行时间
         */
        private final String actionTime;

        /**
         * @param minute n分钟后执行
         */
        private LockTask(int minute) {
            actionTime = DateBuilder.ymdHms(new Date(System.currentTimeMillis() + minute * 60 * 1000L));
        }

        @Override
        public void run() {
            log.info("LockTask.run");
            HRobotJni.clickKey(VK_MEDIA_STOP);
            HRobotJni.lockWorkStation();
            NotMutedFrame.setMute(true);
            lockTask = null; //执行完后,置空task对象
        }
    }

    /**
     * 结束win更新进程
     * 轮询任务
     */
    @SuppressWarnings("SpellCheckingInspection")
    public static class KillWinUpdateTask extends TimerTask {

        public static KillWinUpdateTask doSchedule(Timer timer) {
            KillWinUpdateTask task = new KillWinUpdateTask();
            //timer.schedule(task, 1000, 1000);//test
            timer.schedule(task, 1000, 2 * 60 * 1000L);
            return task;
        }

        @Override
        public void run() {
            try {
                //Integer pid = getSvchostPid("svch");//test
                //Integer pid = getSvchostPid("notepad");//test
                Integer pid = getSvchostPid("wuauserv");
                if (pid == null) return;//没启动,不打印任何日志

                ArrayList<String> killResult = BatchUtil.builder()
                        .maxWaitTime(3000L)
                        .exec("taskkill -f /pid " + pid);
                log.info("结束进程.res=[[{}]]", TextUtil.getLineWrapLog(killResult));
            } catch (Exception e) {
                log.error(AppLogger.getStack("KillWinUpdateTask异常:", e));
            }
        }

        /**
         * @param serviceName win服务名, 参考{@link ScQc}等
         */
        @SuppressWarnings("SameParameterValue")
        private Integer getSvchostPid(String serviceName) {
            ArrayList<String> result = BatchUtil.builder()
                    .maxWaitTime(3000L)
                    .exec("cmd /c tasklist /svc | findstr " + serviceName);
            if (result.isEmpty()) return null;//服务没启动
            if (result.size() != 1) {
                log.warn("查询进程异常? res=\n[{}]", TextUtil.getLineWrapLog(result));
                return null;
            }

                /*
                正常情况===
                "Taskmgr.exe                   2300 暂缺"
                或 空?
                异常情况===
                多行错误文本
                 */
            log.info("查询进程 res={}", result.get(0));
            String pid = result.get(0).split("\\s+")[1];//正则切割多个空格
            return Integer.parseInt(pid);
        }
    }

}
